Skip to content

Introduce multi-period Account data type and use it for MultiBalanceReport and BudgetReport. #2360

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 22 commits into from

Conversation

Xitian9
Copy link
Collaborator

@Xitian9 Xitian9 commented Mar 26, 2025

This rejigs the MultiBalanceReport internals to use an enhanced Account data type to save the values. This has a few effects:

  • A small speed improvement on large journal files with interval reporting, due to processing the posting list in one pass.
  • Simplified program logic, as there was a lot of code to convert back and forth between list and tree representations. This can now be removed.
  • Ability to merge Account means that BudgetReport can be simplified.

There are some small changes in behaviour with respect to budget reports, where it looked like some behaviour was implemented to work around needing to get the budget and actuals into the same shape so they could be merged. This is no longer necessary, but may still be desired for other reasons.

Let me know your thoughts.

@Xitian9 Xitian9 force-pushed the multiaccount branch 5 times, most recently from d8d6312 to 04cb729 Compare March 29, 2025 11:47
@simonmichael simonmichael added needs-review To unblock: needs more code/docs/design review by someone performance Anything performance-related (run time, memory usage, disk space..) labels Apr 2, 2025
Copy link
Owner

@simonmichael simonmichael left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Initial comments.


# ** 16. balance --flat --empty does not display accounts which have not been
# seen, even if they're implied, but does show accounts that have been seen
# with 0 balance.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what this means in userese ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means that if there have never been any postings to assets, then we shouldn't display a value for the assets account, even with --empty. On the other hand, we should show assets:bank:checking, since there have been postings to that account.

This was the case before, but turned out to be a non-trivial thing to maintain in the refactoring, so I added a test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the test description. Let me know if it's clearer.

@@ -50,7 +50,6 @@ Budget performance in 2016-12-01..2016-12-03:
|| 2016-12-01 2016-12-02 2016-12-03
==================++==============================================================
assets:cash || $-10 [ 40% of $-25] $-14 [56% of $-25] $-51 [204% of $-25]
expenses || $10 [ 40% of $25] $14 [56% of $25] $51 [204% of $25]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another behaviour change, worth noting with a ! in message.

The parent "expenses" account is not shown, because there's no explicit budget goal for it, and because we're in list mode ? So if we want to see aggregated budget performance, tree mode will be needed. Ok I guess.

Why is it still shown in the previous test ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me look into this.

Copy link
Collaborator Author

@Xitian9 Xitian9 Apr 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the reason is as follows:

Unless called with -E, then a budget report will count any unbudgeted subaccounts against their earliest budgeted parent. So both expenses:cab and expenses:movies are rolled up to expenses. Even though expenses doesn't have a budget itself, it gets the sum of the budgets of its subaccounts.

I'm not sure how I feel about this behaviour, but I think changing it is out of scope for this PR.

@simonmichael simonmichael added balance balancesheet incomestatement cashflow budget The balance command's --budget report balancesheetequity and removed needs-review To unblock: needs more code/docs/design review by someone labels Apr 3, 2025
@simonmichael
Copy link
Owner

A small speed improvement on large journal files

Could we quantify that a little more - eg "balance reports are 1% faster with 1k txns, 5% faster with 10k txns" ?

@simonmichael
Copy link
Owner

Also I wonder if there's any memory impact, stats might be a quick way to check (it runs balance reports probably)

Xitian9 added 15 commits May 31, 2025 09:29
Rephrase everything in terms of boringness to make for a clearer logical
flow.
This removes the type alias Account, and replaces it with the
fully-qualified name Account AccountBalance. This breaks some backwards
compatibility, but that was already broken by the change of Account type
constructor in any case. This simplifies the interface.
Rename applyAccountBalance to mapAccountBalance.
mergeWithKey can create corrupt output if its inputs don't satisfy
certain conditions. We restrict the domain here to only those cases
where it is guaranteed safe. This still covers all the cases that we
need.
This keeps Hledger.Data.AccountBalance and Hledger.Data.AccountBalances
separate.
If a report would have an empty interval span, which occurs when the
journal is empty, then instead of an empty list, return a singleton
containing the entire report span.
@Xitian9
Copy link
Collaborator Author

Xitian9 commented May 31, 2025

Sorry for the delay. I've rebased against master and pushed a quick fix for the failing test. I think there's a better fix involving a bit more work, but I want to avoid making this PR heavier than it already is.

I've been a bit busy, so haven't yet had the chance to create a separate squashed PR. Please let me know if you still feel that's valuable and I'll try to devote time to it when I can.

Those doc tweaks look good to me. I'll incorporate them as a separate commit rather than rebasing, if you don't mind.

@simonmichael
Copy link
Owner

simonmichael commented May 31, 2025

Thanks for the updates. I don't mind doing an unsquashed merge if it saves time.

We are close to (ideal) release date. I don't want to cause more delay, but prudence would probably say merge this after release so we have more time to flush out surprises. On the other hand it's passing tests. I could probably go either way, do you have a preference ?

@Xitian9
Copy link
Collaborator Author

Xitian9 commented May 31, 2025

Yes, definitely wait. I'm in no hurry, and some extra time for testing would be appropriate for a refactoring of the core code like this.

@Xitian9
Copy link
Collaborator Author

Xitian9 commented May 31, 2025

I've renamed the data constructors and their record names according to your suggestions above. The one exception is I chose one of your alternative names PeriodData instead of PerPeriod. I'm happy to be overruled on that call.

Goals:
- Use names and descriptions matching the generality/specificity of the types
- Use distinctive names not easily confusable with each other
@simonmichael
Copy link
Owner

simonmichael commented May 31, 2025 via email

@simonmichael simonmichael added needs-other-task To unblock: needs some other issue/task/event, possibly outside our project and removed needs-discussion To unblock: needs more discussion/review/exploration needs-rebase To unblock: needs to be rebased against latest master branch labels Jun 4, 2025
@simonmichael
Copy link
Owner

This was merged as #2395.

@simonmichael simonmichael removed the needs-other-task To unblock: needs some other issue/task/event, possibly outside our project label Jun 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
balance balancesheet balancesheetequity budget The balance command's --budget report cashflow incomestatement performance Anything performance-related (run time, memory usage, disk space..)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants